package com.r2coding.server.modules.file.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.r2coding.core.exception.Pan4jException;
import com.r2coding.core.utils.IdUtil;
import com.r2coding.server.common.config.ServerConfig;
import com.r2coding.server.modules.file.context.FileChunkUploadContext;
import com.r2coding.server.modules.file.entity.FileChunk;
import com.r2coding.server.modules.file.enums.MergeFlagEnum;
import com.r2coding.server.modules.file.mapper.FileChunkMapper;
import com.r2coding.server.modules.file.service.IFileChunkService;
import com.r2coding.storage.engine.core.StorageEngine;
import com.r2coding.storage.engine.core.context.StoreFileChunkContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;

/**
 * @author 98k灬
 * @version v1.0.0
 * @Description : 功能描述
 * @Create on : 2023/10/20 12:26
 **/
@Slf4j
@Service
public class IFileChunkServiceImpl extends ServiceImpl<FileChunkMapper, FileChunk> implements IFileChunkService {
    @Autowired
    private ServerConfig serverConfig;

    @Autowired
    private StorageEngine storageEngine;

    /**
     * 文件分片上传
     * 1、保存文件分片和记录
     * 2、判断文件分片是否全部上传完成
     *
     * @param context 分片上传上下文
     */
    @Override
    public synchronized void saveChunkFile(FileChunkUploadContext context) {
        this.doSaveChunkFile(context);
        this.doJudgeMergeFile(context);
    }

    private void doJudgeMergeFile(FileChunkUploadContext context) {
        LambdaQueryWrapper<FileChunk> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileChunk::getIdentifier, context.getIdentifier())
                .eq(FileChunk::getCreateUser, context.getUserId());
        Integer count = this.baseMapper.selectCount(wrapper);
        if (count == context.getTotalChunks().intValue()) {
            context.setMergeFlagEnum(MergeFlagEnum.READY);
        }
    }

    private void doSaveChunkFile(FileChunkUploadContext context) {
        this.doStoreFileChunk(context);
        this.doSaveRecord(context);
    }

    private void doSaveRecord(FileChunkUploadContext context) {
        FileChunk fileChunk = FileChunk.builder()
                .id(IdUtil.get())
                .identifier(context.getIdentifier())
                .realPath(context.getRealPath())
                .chunkNumber(context.getChunkNumber())
                .expirationTime(DateUtil.offsetDay(new Date(), serverConfig.getChunkFileExpirationDays()))
                .createUser(context.getUserId())
                .createTime(new Date())
                .build();
        this.baseMapper.insert(fileChunk);
    }

    private void doStoreFileChunk(FileChunkUploadContext context) {
        try {
            StoreFileChunkContext storeFileChunkContext = new StoreFileChunkContext();
            BeanUtils.copyProperties(context, storeFileChunkContext);
            storeFileChunkContext.setInputStream(context.getFile().getInputStream());
            storageEngine.storeChunk(storeFileChunkContext);
            context.setRealPath(storeFileChunkContext.getRealPath());
        } catch (IOException exception) {
            exception.printStackTrace();
            throw new Pan4jException("文件分片上传失败");
        }
        
    }
}
